target_dir: Path,
doc_dir: Path,
build: Vec<String>, // TODO: deprecated, remove
+ links: Option<String>,
warnings: Vec<String>,
exclude: Vec<String>,
metadata: ManifestMetadata,
env: _,
test: _,
doctest: _,
-
+
custom_build: _,
} = *self;
(opt_level, codegen_units, debug, rpath, for_host, dest, harness).hash(into)
impl Manifest {
pub fn new(summary: Summary, targets: Vec<Target>,
target_dir: Path, doc_dir: Path,
- build: Vec<String>, exclude: Vec<String>,
+ build: Vec<String>, exclude: Vec<String>, links: Option<String>,
metadata: ManifestMetadata) -> Manifest {
Manifest {
summary: summary,
build: build, // TODO: deprecated, remove
warnings: Vec::new(),
exclude: exclude,
+ links: links,
metadata: metadata,
}
}
self.build.as_slice()
}
+ pub fn get_links(&self) -> Option<&str> {
+ self.links.as_ref().map(|s| s.as_slice())
+ }
+
pub fn add_warning(&mut self, s: String) {
self.warnings.push(s)
}
let output = try!(p.exec_with_output().map_err(|mut e| {
e.msg = format!("Failed to run custom build command for `{}`\n{}",
pkg, e.msg);
- e.mark_human()
+ e.concrete().mark_human()
}));
// parsing the output of the custom build script to check that it's correct
--- /dev/null
+use std::collections::HashMap;
+
+use core::PackageSet;
+use util::{CargoResult, human};
+
+// Returns a mapping of the root package plus its immediate dependencies to
+// where the compiled libraries are all located.
+pub fn validate(deps: &PackageSet) -> CargoResult<()> {
+ let mut map = HashMap::new();
+
+ for dep in deps.iter() {
+ let lib = match dep.get_manifest().get_links() {
+ Some(lib) => lib,
+ None => continue,
+ };
+ match map.find(&lib) {
+ Some(previous) => {
+ return Err(human(format!("native library `{}` is being linked \
+ to by more than one package, and \
+ can only be linked to by one \
+ package\n\n {}\n {}",
+ lib, previous, dep.get_package_id())))
+ }
+ None => {}
+ }
+ if !dep.get_manifest().get_targets().iter().any(|t| {
+ t.get_profile().is_custom_build()
+ }) {
+ return Err(human(format!("package `{}` specifies that it links to \
+ `{}` but does not have a custom build \
+ script", dep.get_package_id(), lib)))
+ }
+ map.insert(lib, dep.get_package_id());
+ }
+
+ Ok(())
+}
mod job;
mod job_queue;
mod layout;
+mod links;
#[deriving(PartialEq, Eq)]
pub enum Kind { KindHost, KindTarget }
debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps);
+ try!(links::validate(deps));
+
let dest = uniq_target_dest(targets);
let root = deps.iter().find(|p| p.get_package_id() == resolve.root()).unwrap();
let host_layout = Layout::new(root, None, dest);
version: TomlVersion,
authors: Vec<String>,
build: Option<TomlBuildCommandsList>, // TODO: `String` instead
+ links: Option<String>,
exclude: Option<Vec<String>>,
// package metadata
layout.root.join("doc"),
old_build,
exclude,
+ project.links.clone(),
metadata);
if used_deprecated_lib {
manifest.add_warning(format!("the [[lib]] section has been \
-use std::path;
-
use support::{project, execs};
use support::{COMPILING, RUNNING};
use hamcrest::{assert_that};
)));
})
*/
+
+test!(links_no_build_cmd {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ "#)
+ .file("src/lib.rs", "");
+
+ assert_that(p.cargo_process("build"),
+ execs().with_status(101)
+ .with_stderr("\
+package `foo v0.5.0 (file://[..])` specifies that it links to `a` but does \
+not have a custom build script
+"));
+})
+
+
+test!(links_duplicates {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+
+ [dependencies.a]
+ path = "a"
+ "#)
+ .file("src/lib.rs", "")
+ .file("build.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ links = "a"
+ build = "build.rs"
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("a/build.rs", "");
+
+ assert_that(p.cargo_process("build"),
+ execs().with_status(101)
+ .with_stderr("\
+native library `a` is being linked to by more than one package, and can only be \
+linked to by one package
+
+ foo v0.5.0 (file://[..])
+ a v0.5.0 (file://[..])
+"));
+})
+